﻿using System;
using System.Collections.Generic;
using System.Net;
using HtmlAgilityPack;


namespace CCPSIP
{
  public class IPPbxKitV2
  {
    private const string kIPPbxVersion = "cs210_02";
    private const string kDefaultServer = "172.18.27.200";
    private static System.Text.Encoding PageEncoding = System.Text.Encoding.GetEncoding(950);//Big5
    private static WebProxy DefaultProxy = new WebProxy();


    public static Dictionary<string, string> GetUserData(string phoneNumber) {
      string targetPage = string.Format("https://{0}/usrch.php?phone={1}", kDefaultServer, phoneNumber);

      HtmlDocument htmlDoc = new HtmlDocument();
      htmlDoc.LoadHtml(GetWebHtml(targetPage));

      HtmlNodeCollection paramNodes = htmlDoc.DocumentNode.SelectNodes("//input | //select");
      if (paramNodes == null) {
        throw new Exception("Error: PARAM_NODE_NOT_FOUND");
      }
      else if (paramNodes.Count < 34) {
        throw new Exception("Error: PARAM_NODE_NOT_ENOUGH");
      }

      Dictionary<string, string> paramDict = new Dictionary<string, string>();
      foreach (HtmlNode paramNode in paramNodes) {
        if (paramNode.Name == "input") {
          if (paramNode.Attributes.Contains("type")) {
            string inputType = paramNode.Attributes["type"].Value;
            if (inputType == "Submit" || inputType == "reset")
              continue;
          }
          if (paramNode.Attributes.Contains("name")) {
            string paramName = paramNode.Attributes["name"].Value;

            if (paramNode.Attributes.Contains("value"))
              paramDict[paramName] = paramNode.Attributes["value"].Value;
            else
              paramDict[paramName] = "";
          }
        }
        else if (paramNode.Name == "select") {
          HtmlNode selectedNode = paramNode.SelectSingleNode("option[@selected]");
          if (selectedNode == null) {
            selectedNode = paramNode.SelectSingleNode("option");
          }
          string paramName = paramNode.Attributes["name"].Value;
          string paramValue = selectedNode.Attributes["value"].Value;
          paramDict[paramName] = paramValue;
        }
      }
      paramDict.Remove("OK");
      return paramDict;
    }


    public static string UpdateUser(Dictionary<string, string> paramDict) {
      string targetPage = string.Format("https://{0}/usrch.php", kDefaultServer);

      HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(targetPage);
      ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
      webReq.ProtocolVersion = HttpVersion.Version11;
      webReq.Method = "POST";
      webReq.Timeout = 30 * 1000;
      webReq.KeepAlive = false;
      webReq.AllowAutoRedirect = false;
      webReq.Proxy = DefaultProxy;
      webReq.ContentType = "application/x-www-form-urlencoded; charset=Big5";

      paramDict["OK"] = "YES";
      paramDict["send"] = "確定";
      string paramStr = ChrisKit.DictToQueryStr(paramDict, PageEncoding);

      byte[] postBytes = PageEncoding.GetBytes(paramStr);
      webReq.ContentLength = postBytes.Length;
      using (System.IO.Stream reqStream = webReq.GetRequestStream()) {
        reqStream.Write(postBytes, 0, postBytes.Length);
        reqStream.Flush();
        reqStream.Close();
      }
      HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
      webResp.Close();

      return "OK";
    }


    public static string[] GetGatewayGroupList() {
      string targetPage = string.Format("https://{0}/gw2grp.php", kDefaultServer);

      HtmlDocument htmlDoc = new HtmlDocument();
      htmlDoc.LoadHtml(GetWebHtml(targetPage));

      HtmlNodeCollection inputNodes = htmlDoc.DocumentNode.SelectNodes("//input[@value='內容']");
      List<string> GatewayGroupList = new List<string>();
      foreach (HtmlNode inputNode in inputNodes) {
        string action = inputNode.Attributes["onClick"].Value;
        if (action.StartsWith("updateUnit(")) {
          int startIndex = action.IndexOf("('") + 2;
          int endIndex = action.IndexOf("')");
          string ggName = action.Substring(startIndex, endIndex - startIndex);
          GatewayGroupList.Add(ggName);
        }
      }
      return GatewayGroupList.ToArray();
    }


    public static string[] GetGatewayList(string GroupName) {
      string targetPage = string.Format("https://{0}/gw2.php?unit={1}", kDefaultServer, GroupName);

      HtmlDocument htmlDoc = new HtmlDocument();
      htmlDoc.LoadHtml(GetWebHtml(targetPage));

      HtmlNodeCollection uInputNodes = htmlDoc.DocumentNode.SelectNodes("//input[@value='修改']");
      List<string> gwSettingList = new List<string>();
      foreach (HtmlNode uInputNode in uInputNodes) {
        string action = uInputNode.Attributes["onClick"].Value;
        if (action.StartsWith("updateGW(")) {
          int startIndex = action.IndexOf(",'") + 2;
          int endIndex = action.IndexOf("')");
          string GatewayName = action.Substring(startIndex, endIndex - startIndex);
          gwSettingList.Add(GetGatewaySetting(GroupName, GatewayName));
        }
      }
      return gwSettingList.ToArray();
    }


    private static string GetGatewaySetting(string GroupName, string GatewayName) {
      string targetPage = string.Format("https://{0}/gw2ch.php?gateway={1}&unit={2}", kDefaultServer, GatewayName, GroupName);

      HtmlDocument htmlDoc = new HtmlDocument();
      htmlDoc.LoadHtml(GetWebHtml(targetPage));

      HtmlNode gwNode = htmlDoc.DocumentNode.SelectSingleNode("//input[@name='gateway']");
      string gateway = gwNode.Attributes["value"].Value;
      HtmlNode ipNode = htmlDoc.DocumentNode.SelectSingleNode("//input[@name='ip']");
      string gatewayIP = ipNode.Attributes["value"].Value;

      HtmlNodeCollection optionNodes = htmlDoc.DocumentNode.SelectNodes("//option[@selected]");
      string[] codecArray = new string[3];
      if (optionNodes.Count == codecArray.Length) {
        for (int i = 0; i < codecArray.Length; i++) {
          codecArray[i] = optionNodes[i].Attributes["value"].Value;
        }
      }
      return string.Format("{0}\t{1}\t{2}", gateway, gatewayIP, string.Join(":", codecArray));
    }


    public static string[] GetDialPlanList(string GroupName) {
      string targetPage = string.Format("https://{0}/gw2.php?unit={1}", kDefaultServer, GroupName);

      HtmlDocument htmlDoc = new HtmlDocument();
      htmlDoc.LoadHtml(GetWebHtml(targetPage));

      HtmlNodeCollection dInputNodes = htmlDoc.DocumentNode.SelectNodes("//input[@value='刪除']");
      List<string> dialPlanList = new List<string>();
      foreach (HtmlNode dInputNode in dInputNodes) {
        string action = dInputNode.Attributes["onClick"].Value;
        if (action.StartsWith("removeGWCxt(")) {
          int startIndex = action.IndexOf(",'") + 2;
          int endIndex = action.IndexOf("')");
          string dialPlan = action.Substring(startIndex, endIndex - startIndex);
          dialPlanList.Add(dialPlan);
        }
      }
      return dialPlanList.ToArray();
    }


    private static string GetWebHtml(string webUrl) {
      const int kRespMaxKB = 3000;//in KB
      try {
        HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(webUrl);
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        webReq.ProtocolVersion = HttpVersion.Version11;
        webReq.Method = "GET";
        webReq.Timeout = 30 * 1000;
        webReq.KeepAlive = false;
        webReq.AllowAutoRedirect = false;
        webReq.Proxy = DefaultProxy;

        HttpWebResponse webResp = (HttpWebResponse)webReq.GetResponse();
        System.IO.Stream respStream = webResp.GetResponseStream();
        byte[] pageBytes = new byte[kRespMaxKB * 1024];
        int bytesCount = 0;

        for (int i = 0; i < kRespMaxKB; i++) {
          int readCount = respStream.Read(pageBytes, bytesCount, 1024);
          if (readCount == 0)
            break;
          else
            bytesCount += readCount;
        }
        respStream.Close();
        webResp.Close();

        return PageEncoding.GetString(pageBytes, 0, bytesCount);
      }
      catch (Exception ex) {
        throw ex;
      }
    }

  }
}